package com.mini.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CalendarUtil {
    private static final Logger log = LoggerFactory.getLogger(CalendarUtil.class);
    public static final String CREDIT_CARD_DATE_FORMAT = "MM/yyyy";
    public static final String SHORT_DATE_FORMAT = "yyyy-MM-dd";
    public static final String SHORT_DATE_FORMAT_CHN = "MM月dd日";
    public static final String SHORT_DATE_FORMAT_YYYY_MM = "yyyy-MM";
    public static final String SHORT_DATE_FORMAT_YYYY_MM_DD_HH = "yyyy-MM-dd HH:mm";
    public static final String SHORT_DATE_DOT_FORMAT = "yyyy.MM.dd";
    public static final String SHORT_DATE_FORMAT_NO_DASH = "yyyyMMdd";
    public static final String SIMPLE_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String SIMPLE_DATE_FORMAT_NO_DASH = "yyyyMMddHHmmss";
    public static final String LOG_DATE_FORMAT = "yyyyMMdd_HH00";
    public static final String ZONE_DATE_FORMAT = "EEE yyyy-MM-dd HH:mm:ss zzz";
    public static final String DATE_FORMAT = "yyyy/MM/dd EEE";
    public static final String TIME_FORMAT = "HH:mm";
    public static final String SHORT_DATA_FORMAT_YYYY_MMDD = "yyyy/MMdd";
    public static final String TIME_FULL_FORMAT = "HH:mm:ss";

    /**
     * 获得默认格式化时间 'yyyy-MM-dd'
     *
     * @param date
     * @return
     */
    public static String getShortDateString(Date date) {
        if (null == date) {
            return "";
        }
        return getDateString(date, SHORT_DATE_FORMAT);
    }

    /**
     * Return the String representation of the Date against the given format.
     *
     * @param date the date to format
     * @param format the date format pattern
     * @return the format Date String.
     */
    public static String getDateString(Date date, String format) {
        if (date == null) {
            return null;
        }

        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }

    public static String getShortHHmmDateString(Date date) {
        return getDateString(date , SHORT_DATE_FORMAT_YYYY_MM_DD_HH);
    }

    /**
     * 将string转换成date类型数据
     *
     * @param dateString
     * @return
     */
    public static Date parseDefaultDate(String dateString) {
        if (!StringUtils.hasText(dateString)) {
            return null;
        }
        Date date = null;
        try {
            DateFormat format = new SimpleDateFormat(SIMPLE_DATE_FORMAT);
            date = format.parse(dateString);
        } catch (ParseException ex) {
            log.error("Invalid date string: " + dateString, ex);
            throw new IllegalArgumentException("Invalid date string: " + dateString, ex);
        }

        return date;
    }

    /**
     * 将string转换成date类型数据
     *
     * @param dateString
     * @return
     */
    public static Date parseShortDate(String dateString) {
        if (!StringUtils.hasText(dateString)) {
            return null;
        }
        Date date = null;
        try {
            DateFormat format = new SimpleDateFormat(SHORT_DATE_FORMAT);
            date = format.parse(dateString);
        } catch (ParseException ex) {
            log.error("Invalid date string: " + dateString, ex);
            throw new IllegalArgumentException("Invalid date string: " + dateString, ex);
        }

        return date;
    }

    /**
     * 将string转换成date类型数据
     *
     * @param dateString
     * @return
     */
    public static Date parseDate(String dateString,String format) {
        if (!StringUtils.hasText(dateString)) {
            return null;
        }
        Date date = null;
        try {
            DateFormat dateFormat = new SimpleDateFormat(format);
            date = dateFormat.parse(dateString);
        } catch (ParseException ex) {
            log.error("Invalid date string: " + dateString, ex);
            throw new IllegalArgumentException("Invalid date string: " + dateString, ex);
        }

        return date;
    }

    public static String getBeforDay(){
        Calendar cal=Calendar.getInstance();
        cal.add(Calendar.DATE,-1);
        Date d=cal.getTime();


        SimpleDateFormat sp=new SimpleDateFormat("yyyy-MM-dd");
        return sp.format(d);
    }

    public static String getBeforDay(String dateStr){
        Date date = parseDate(dateStr, SHORT_DATE_FORMAT);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE,-1);
        Date d=cal.getTime();
        SimpleDateFormat sp=new SimpleDateFormat(SHORT_DATE_FORMAT);
        return sp.format(d);
    }

    /**
     * 把long 转换成 日期 再转换成String类型
     */
    public static String transferLongToStringDate(String dateFormat, Long millSec) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        Date date = new Date(millSec);
        return sdf.format(date);
    }


    /**
     * 把long 转换成 日期 再转换成String类型
     */
    public static Date transferLongToDate(Long millSec) {
        Date date = new Date(millSec);
        return date;
    }

    public static Date beforeHourToNowDate(int hour) {
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - hour);
        /* MINUTE 指示一天中的某分 */
//        calendar.set(Calendar.MINUTE,(calendar.get(Calendar.MINUTE) - 50));
        return calendar.getTime();
//        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        System.out.println("一个小时前的时间：" + df.format(time));
//        System.out.println("当前的时间：" + df.format(new Date()));
    }

    public static Date beforeMinuteToNowDate(int minutes) {
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中小时 */
//        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        /* MINUTE 指示一天中的某分 */
        calendar.set(Calendar.MINUTE,(calendar.get(Calendar.MINUTE) - minutes));
        return calendar.getTime();
//        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        System.out.println("一个小时前的时间：" + df.format(time));
//        System.out.println("当前的时间：" + df.format(new Date()));
    }

    public static Date deviceMinuteToNowDate(int minutes) {
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中小时 */
//        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        /* MINUTE 指示一天中的某分 */
        calendar.add(Calendar.MINUTE, minutes);
        return calendar.getTime();
//        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        System.out.println("一个小时前的时间：" + df.format(time));
//        System.out.println("当前的时间：" + df.format(new Date()));
    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
     * @param startTime
     * @param endTime
     * @return
     */
    public static boolean isEffectiveDate(String startTime, String endTime,String dateFormat) throws ParseException {
        DateFormat df = new SimpleDateFormat(dateFormat);

        Date nowDate = df.parse(df.format(new Date()));
        Date startDate = df.parse(startTime);
        Date endDate = df.parse(endTime);

        if (nowDate.getTime() == startDate.getTime()
                || nowDate.getTime() == endDate.getTime()) {
            return true;
        }

        return isEffectiveDate(nowDate,startDate,endDate);
    }
    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致
     *
     * @param nowTime 当前时间
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @return
     */
    public static boolean isEffectiveDate(Date nowTime, Date startTime, Date endTime) {
        if (nowTime.getTime() == startTime.getTime()
                || nowTime.getTime() == endTime.getTime()) {
            return true;
        }


        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);


        Calendar begin = Calendar.getInstance();
        begin.setTime(startTime);


        Calendar end = Calendar.getInstance();
        end.setTime(endTime);


        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isEffectiveDate(String endTime,String dateFormat) throws ParseException {

        DateFormat df = new SimpleDateFormat(dateFormat);

        Date nowDate = df.parse(df.format(new Date()));
        Date endDate = df.parse(df.format(parseDefaultDate(endTime)));

        if (nowDate.getTime() == endDate.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowDate);

        Calendar end = Calendar.getInstance();
        end.setTime(endDate);


        if (date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isEffectiveDateCheck(String endTime,String dateFormat) {

        DateFormat df = new SimpleDateFormat(dateFormat);
        Date nowDate = null;
        Date endDate = null;
        try {
            nowDate = df.parse(df.format(getEndTime(new Date())));
            endDate = df.parse(df.format(parseDefaultDate(endTime)));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if (nowDate.getTime() == endDate.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowDate);

        Calendar end = Calendar.getInstance();
        end.setTime(endDate);

        if (date.before(end)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isEffective2Days(String endTime,String dateFormat) {

        DateFormat df = new SimpleDateFormat(dateFormat);
        Date nowDate = null;
        Date endDate = null;
        try {
            nowDate = df.parse(df.format(getEndDayOfTomorrow(new Date() , 1)));
            endDate = df.parse(df.format(parseDefaultDate(endTime)));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if (nowDate.getTime() == endDate.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowDate);

        Calendar end = Calendar.getInstance();
        end.setTime(endDate);

        if (end.before(date)) {
            return true;
        } else {
            return false;
        }
    }

    public static boolean isEffective7Days(String endTime,String dateFormat) {

        DateFormat df = new SimpleDateFormat(dateFormat);
        Date nowDate = null;
        Date endDate = null;
        try {
            nowDate = df.parse(df.format(getEndDayOfTomorrow(new Date() , 7)));
            endDate = df.parse(df.format(parseDefaultDate(endTime)));
        } catch (ParseException e) {
            e.printStackTrace();
        }

        if (nowDate.getTime() == endDate.getTime()) {
            return true;
        }

        Calendar date = Calendar.getInstance();
        date.setTime(nowDate);

        Calendar end = Calendar.getInstance();
        end.setTime(endDate);

        if (end.before(date)) {
            return true;
        } else {
            return false;
        }
    }

    public static Date convertDateStr2Date(String dateStr){
        LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ISO_DATE);
        ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zonedDateTime.toInstant());
    }

    public static Date convertTimeStr2Time(String dateStr,String timeStr){
        LocalDate localDate = LocalDate.parse(dateStr, DateTimeFormatter.ISO_DATE);
        LocalTime localTime = LocalTime.parse(timeStr,DateTimeFormatter.ISO_TIME);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = LocalDateTime.of(localDate, localTime).atZone(zone).toInstant();
        return Date.from(instant);
    }

    /**
     * 3位整数
     * @return
     */
    public static int autoId(){
        Random rand = new Random();
        //[900]：900个    100：从100
        int x = rand.nextInt(900) + 100;
        return x;
    }

    public static List<String> getDays(String startTime, String endTime) {

        // 返回的日期集合
        List<String> days = new ArrayList<String>();

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);

            Calendar tempStart = Calendar.getInstance();
            tempStart.setTime(start);

            Calendar tempEnd = Calendar.getInstance();
            tempEnd.setTime(end);
            tempEnd.add(Calendar.DATE, +1);// 日期加1(包含结束)
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

        return days;
    }

    public static Date getStartTime(Date date) {
        Calendar dateStart = Calendar.getInstance();
        dateStart.setTime(date);
        dateStart.set(Calendar.HOUR_OF_DAY, 0);
        dateStart.set(Calendar.MINUTE, 0);
        dateStart.set(Calendar.SECOND, 0);
        return dateStart.getTime();
    }

    public static Date getEndTime(Date date) {
        Calendar dateEnd = Calendar.getInstance();
        dateEnd.setTime(date);
        dateEnd.set(Calendar.HOUR_OF_DAY, 23);
        dateEnd.set(Calendar.MINUTE, 59);
        dateEnd.set(Calendar.SECOND, 59);
        return dateEnd.getTime();
    }

    /**
     * 获取某天之前或者之后的数据
     *
     * @param dateStr
     * @param count
     * @return
     */
    public static String getDate(String dateStr , Integer count){
        Date date = parseDate(dateStr, SHORT_DATE_FORMAT_YYYY_MM_DD_HH);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE,count);
        Date d=cal.getTime();
        SimpleDateFormat sp=new SimpleDateFormat(SHORT_DATE_FORMAT_YYYY_MM_DD_HH);
        return sp.format(d);
    }

    /**
     * 获取某天之前或者之后的开始时间
     *
     * @return 默认格式 Wed May 31 14:47:18 CST 2017
     */
    public static Date getBeginDayOfTomorrow(Date date , Integer count) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getStartTime(new Date()));
        cal.add(Calendar.DAY_OF_MONTH, count);

        return cal.getTime();
    }

    /**
     * 获取某天之前或者之后的结束时间
     * @return 默认格式 Wed May 31 14:47:18 CST 2017
     */
    public static Date getEndDayOfTomorrow(Date date , Integer count) {
        Calendar cal = new GregorianCalendar();
        cal.setTime(getEndTime(new Date()));
        cal.add(Calendar.DAY_OF_MONTH, count);
        return cal.getTime();
    }

    public static String getBeginNCountTime(Date date , Integer count){
        return getDateString(getBeginDayOfTomorrow(date , count) , SHORT_DATE_FORMAT_YYYY_MM_DD_HH);
    }

    public static String getEndNCountTime(Date date , Integer count){
        return getDateString(getEndDayOfTomorrow(date , count) , SHORT_DATE_FORMAT_YYYY_MM_DD_HH);
    }

    public static long getMinute(){
        long currency = System.currentTimeMillis();
        long endTime = CalendarUtil.getEndTime(new Date()).getTime();
        return (endTime - currency) / (1000 * 60);
    }

    public static boolean isValidDate(String str) {
        boolean convertSuccess = true;
        // 指定日期格式为四位年/两位月份/两位日日期
        SimpleDateFormat format = new SimpleDateFormat(SHORT_DATE_FORMAT_YYYY_MM_DD_HH);
        try {
            format.setLenient(false);
            format.parse(str);
        } catch (ParseException e) {
            convertSuccess = false;
        }
        return convertSuccess;
    }

    public static void main(String[] args) {
//        List<String> days = CalendarUtil.getDays("2020-06-17 00:00:00", "2020-06-19 23:00:00");
//        System.out.println(days);

//        String formatDate = "2020-06-22 23:50" + ":00";
//        System.out.println(CalendarUtil.isEffectiveDateCheck(formatDate, SHORT_DATE_FORMAT_YYYY_MM_DD_HH));

//        System.out.println(CalendarUtil.getEndNCountTime(new Date() , 3));

//        long l = System.currentTimeMillis();
//        Date date = CalendarUtil.transferLongToDate(l);
//        String dateString = CalendarUtil.getDateString(date, CalendarUtil.SIMPLE_DATE_FORMAT);
//        System.out.println(" l = "+ l +" , str===== 【" + dateString + " 】");

//        String time = "2020-06-03 12:00:00";
//        System.out.println(time.substring(time.indexOf(" ")+1));

    }

}
